package com.xone.xapp;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import org.json.JSONObject;

import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;

/**
 * 订阅服务
 * @author Hunny
 */
public class SubscribeService extends Service {

	private final static String TAG = SubscribeService.class.getSimpleName();

	@Override
	public IBinder onBind(Intent arg0) {
		Log.i(TAG, "SubscribeService onBind.");
		return null;
	}

	@Override
	public boolean onUnbind(Intent intent) {
		Log.i(TAG, "SubscribeService onUnbind.");
		return super.onUnbind(intent);
	}

	@Override
	public void onCreate() {
		Log.i(TAG, "SubscribeService onCreate.");
		super.onCreate();
	}

	@Override
	public void onStart(Intent intent, int startId) {
		Log.i(TAG, "SubscribeService onStart.");
		super.onStart(intent, startId);
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.i(TAG, "SubscribeService onStartCommand.");
		cancelAlarm();//一有消息，先取消设定的时间执行，这时会直接按原逻辑执行
		doRequest();
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onDestroy() {
		Log.i(TAG, "SubscribeService onDestroy.");
		//2. 应用退出时，Service关闭，在Service的onDestroy方法中取消监听：
		//取消监听
		cancelAlarm();
		super.onDestroy();
	}
	
	/**
	 * 发出http请求，查看是不是有新的订阅消息
	 */
	protected void doRequest() {
		Log.i(TAG, "Tigger doRequest.");
		if (!ContextUtils.isOnline(this)) {//如果没有网络，则不执行网络请求
			return;
		}
		String username = ShareUtils.getPrefs(ShareUtils.USERNAME, getContext());
		String password = ShareUtils.getPrefs(ShareUtils.PASSWROR, getContext());
		if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {//如果本地没有保存用户信息，则也不用去请求
			ShareUtils.setPrefs(Constants.LAST_SUBSCRIBE_DATE_KEY, null, getContext());//没有用户名和密码，就清除订阅的时间
			return;
		}
		String sDate = ShareUtils.getPrefs(Constants.LAST_SUBSCRIBE_DATE_KEY, this);
		// 判断日期时间
		Date date = DateUtils.parseDate(sDate);
		if (date == null) {//如果日期为空，就先补上日期
			date = new Date();
			tagAction(date);
		}
		Log.i(TAG, "Client Time:" + date);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		calendar.add(Calendar.MINUTE, -1 * Constants.SUBSCRIBE_TIMEOUT);//订阅的时间间隔
		Log.i(TAG, "Calendar Time:" + calendar.getTime());
		if (calendar.getTime().compareTo(date) >= 0) {
			//当前的手机所使用的User-Agent
			Constants.USER_AGENT(this);
			//两个参数，第一个是请求的地址，第二个是请求的参数
			new InitDataTask(this).execute("/assistant/subscribeJson.html", DateUtils.format(date));
		} else {//需要计算多长时间后再请求
			int seconds = (int) ((date.getTime() - calendar.getTime().getTime()) / 1000);//单位为秒
			//多长时间之后再提醒
			Log.i(TAG, "" + seconds + "秒之后再提醒");
			startAlarm(seconds);
		}
	}
	
	protected Context getContext() {
		return this;
	}
	
	protected PendingIntent getSubscribePendingIntent() {
		Log.i(TAG, "Tigger PendingIntent getSubscribePendingIntent");
		// 设置一个PendingIntent对象，发送广播
		Intent intent = new Intent(this, SubscribeReceiver.class);
		intent.setAction(Constants.BROADCAST_SERVICE_ACTION);
		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 注意，必须添加这个标记，否则启动会失败
		PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);//PendingIntent.FLAG_NO_CREATE
		return pendingIntent;
	}
	
	/**
	 * timeout秒之后再提醒
	 * @param timeout
	 */
	protected void startAlarm(int timeout) {
		AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
		// 获取AlarmManager对象, 设定一个时间
		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(System.currentTimeMillis());
		calendar.add(Calendar.SECOND, timeout);
		alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), getSubscribePendingIntent());
		Log.i(TAG, "Start Alarm after:" + calendar.getTime());
	}
	
	protected void cancelAlarm() {
		// 设置一个PendingIntent对象，发送广播
		AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
		alarmManager.cancel(getSubscribePendingIntent());
		Log.i(TAG, "Cancel Alarm");
	}
	
	/**
	 * 标记当时的请求日期
	 */
	void tagAction(Date date) {
		Log.i(TAG, "tag action:" + date);
		ShareUtils.setPrefs(Constants.LAST_SUBSCRIBE_DATE_KEY, DateUtils.format(date), getContext());
	}

	// 默认显示的的Notification
	protected void showNotification(final List<NotificationBean> list) {
		
		for (int i = 0; i < list.size(); i++) {
			final int n = i;
			// 注册此通知, 如果该NOTIFICATION_ID的通知已存在，会显示最新通知的相关信息 ，比如tickerText 等
			new Handler().postDelayed(new Runnable(){
			    public void run() {
			    	NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
					NotificationBean bean = list.get(n);
			    	mNotificationManager.notify(n + 1, createNotification(bean));
			    }
			 }, i * 200);
		}
	}
	
	protected Notification createNotification(NotificationBean bean) {
		// 定义Notication的各种属性
		// 创建一个通知
		Notification mNotification = new Notification();
		// 设置属性值
		mNotification.icon = R.drawable.ic_launcher;
		mNotification.tickerText = bean.getTickerText();
		mNotification.when = System.currentTimeMillis(); // 立即发生此通知
		// 添加声音效果
		mNotification.defaults |= Notification.DEFAULT_SOUND;
		// 添加震动,后来得知需要添加震动权限 : Virbate Permission
		// mNotification.defaults |= Notification.DEFAULT_VIBRATE ;

		// 添加状态标志, FLAG_AUTO_CANCEL 该通知能被状态栏的清除按钮给清除掉
		mNotification.flags = Notification.FLAG_AUTO_CANCEL;
		Intent intent = new Intent();
		intent.setAction(Long.toString(System.currentTimeMillis()));
		intent.setClass(getContext(), SubscribeMatcherListAcitvity.class);
		Bundle extras = new Bundle();
		Log.i(TAG, "设置名称:" + bean.getName());
		extras.putString("name", bean.getName());
		if (StringUtils.isNotBlank(bean.getCredit())) {
			extras.putString("credit", bean.getCredit());
		}
		if (StringUtils.isNotBlank(bean.getSaleType())) {
			extras.putString("saleType", bean.getSaleType());
		}
		if (StringUtils.isNotBlank(bean.getMarket())) {
			extras.putString("area", bean.getMarket());
		}
		if (StringUtils.isNotBlank(bean.getQueryDate())) {
			extras.putString("dateCreated", bean.getQueryDate());
		}
		intent.putExtras(extras);
		intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
		// 将该通知显示为默认View, 最的一个参数的含义
		/**
		 * int FLAG_CANCEL_CURRENT：如果该PendingIntent已经存在，则在生成新的之前取消当前的。
		 * int FLAG_NO_CREATE：如果该PendingIntent不存在，直接返回null而不是创建一个PendingIntent.
		 * int FLAG_ONE_SHOT:该PendingIntent只能用一次，在send()方法执行后，自动取消。
		 * int FLAG_UPDATE_CURRENT：如果该PendingIntent已经存在，则用新传入的Intent更新当前的数据
		 */
		PendingIntent contentIntent = PendingIntent.getActivity(getContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
		// 设置setLatestEventInfo方法,如果不设置会App报错异常
		mNotification.setLatestEventInfo(getContext(), bean.getTitle(), bean.getMessage(), contentIntent);
		return mNotification;
	}
	
	/**
	 * @author hunnyhu
	 */
	public class InitDataTask extends AsyncTask<String, Integer, List<NotificationBean>> {
		protected Context context;
		public InitDataTask(Context context) {
			this.context = context;
		}
		@Override
		protected List<NotificationBean> doInBackground(final String... params) {
			if (isCancelled()) {
				return null;
			}
			return HttpUtils.httpGet(Constants.APP_URL + params[0] + "?dateCreated=" + StringUtils.encode(params[1]), null, 
				new HttpUtils.onGetSuccessListener<List<NotificationBean>>() {
					@Override
					public List<NotificationBean> onSuccess(int status, String result) {
						if (HttpUtils.SC_OK == status) {
							List<JSONObject> jsonList = JSONUtils.getJSONListFromIdentifyString(result, "list");
							if (null != jsonList && !jsonList.isEmpty()) {
								List<NotificationBean> list = new ArrayList<NotificationBean>();
								for (JSONObject object : jsonList) {
									NotificationBean bean = new NotificationBean();
									bean.setId(JSONUtils.getStringFromJSONObject(object, "id"));
									bean.setTickerText("有新的订阅消息");
									String name = JSONUtils.getStringFromJSONObject(object, "productNameKey");
									bean.setName(name);
									bean.setTitle(name + "有新的订阅消息");
									StringBuffer buffer = new StringBuffer();
									String saleType = JSONUtils.getStringFromJSONObject(object, "saleTypeName");
									if (StringUtils.isNotBlank(saleType)) {
										buffer.append("类型:");
										buffer.append(saleType);
										bean.setSaleType(JSONUtils.getStringFromJSONObject(object, "saleType"));
									}
									String creditName = JSONUtils.getStringFromJSONObject(object, "creditName");
									if (StringUtils.isNotBlank(creditName)) {
										buffer.append(",信誉:");
										buffer.append(creditName);
										bean.setCredit(JSONUtils.getStringFromJSONObject(object, "credit"));
									}
									String marketarea = JSONUtils.getStringFromJSONObject(object, "marketarea");
									if (StringUtils.isNotBlank(marketarea)) {
										buffer.append(",市场:");
										buffer.append(marketarea);
										bean.setMarket(marketarea);
									}
									bean.setQueryDate(params[1]);//设置查询的时间
									bean.setMessage(buffer.toString());
									list.add(bean);
								}
								return list;
							}
							return Collections.emptyList();
						} else if (HttpUtils.SC_UNAUTHORIZED == status && null != result) {//需要登录的情况
							String username = ShareUtils.getPrefs(ShareUtils.USERNAME, getContext());
							String password = ShareUtils.getPrefs(ShareUtils.PASSWROR, getContext());
							if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) {
								new AutoLoginDataTask(getContext()) {
									@Override
									public void loginOk(JSONObject userMap) {//自动登录成功后再执行一次
										new InitDataTask(getContext()).execute(params);
									}
									@Override
									public void loginFailed(String msg) {//登录失败，不做啥事
										Log.d(TAG, "自动登录失败。");
									}
								}.execute(username, password, result);
							}
						}
						return null;
					}
				});
		}
		@Override
		protected void onPostExecute(List<NotificationBean> result) {
			super.onPostExecute(result);
			if (null != result) {//返回不为null,证明请求有效，则需要设定下一次访问的时间
				if (!result.isEmpty()) {
					showNotification(result);
					Log.i(TAG, "已经有新的订阅消息了。");
				}
				tagAction(new Date());//标记当时请求的时间，便于计算下次是什么时候请求
				startAlarm(Constants.SUBSCRIBE_TIMEOUT * 60);//设置下次的提醒时间
			}
		}
	}
	
	/**
	 * 数据载体
	 * @author hunnyhu
	 */
	public class NotificationBean {
		protected String id;
		protected String tickerText;
		protected String title;
		protected String message;
		protected String name;
		protected String market;
		protected String saleType;
		protected String credit;
		protected String queryDate;
		public String getId() {
			return id;
		}
		public void setId(String id) {
			this.id = id;
		}
		public String getTickerText() {
			return tickerText;
		}
		public void setTickerText(String tickerText) {
			this.tickerText = tickerText;
		}
		public String getTitle() {
			return title;
		}
		public void setTitle(String title) {
			this.title = title;
		}
		public String getMessage() {
			return message;
		}
		public void setMessage(String message) {
			this.message = message;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public String getMarket() {
			return market;
		}
		public void setMarket(String market) {
			this.market = market;
		}
		public String getSaleType() {
			return saleType;
		}
		public void setSaleType(String saleType) {
			this.saleType = saleType;
		}
		public String getCredit() {
			return credit;
		}
		public void setCredit(String credit) {
			this.credit = credit;
		}
		public String getQueryDate() {
			return queryDate;
		}
		public void setQueryDate(String queryDate) {
			this.queryDate = queryDate;
		}
	}
}
